#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cx_common.h"
#include "cx_hal.h"
#include "cx_init.h"
#include "cx_record.h"
#include "video_h264.h"
#include "app_codec.h"
#include "aos/kernel.h"
#include "g711.h"
#include "audio_process.h"
#include "h264_vpu.h"
#include "mm_config.h"

void *cxrecord_hdl;
static long long video_encode_start_time;
static long long audio_encode_start_time;
static int app_hal_get_raw_image(int cam_id, char *data, cx_raw_img_type_e *type, int *width, int *height)
{
	if (data == NULL) {
		printf("error input data NULL\n");
		return -1;
	}

	int size = 360 * 640 * 4;
	memcpy(data, (void *)MM_IMAGE_DPU_BUF0, size);
	*type = CX_IMAGE_FORMAT_BGRA;
	*width = 360;
	*height = 640;

	return size;
}

#define CODEC_RECV_BUFF_LEN     (16 * 2 * 40)      // 40 ms audio
int app_hal_get_encoded_audio(void *data, long long *timestamp)
{
    int ret;
    int offset = 0;
    uint8_t *data_buf = (uint8_t *)data;
    uint8_t recv_data[CODEC_RECV_BUFF_LEN];
    ret = app_codec_input_read(timestamp, recv_data, CODEC_RECV_BUFF_LEN);
	*timestamp += (audio_encode_start_time + 40);
    if (ret > 0) {
        for (int i = 0; i < (ret/4); i++) {
            data_buf[offset++] = linear2alaw(*(int16_t *)&recv_data[i * 4]);
        }
    } else {
        return 0;
    }
    return offset;
}

int app_hal_get_encoded_video(void *data, uint32_t max_size, int *is_iframe, long long *timestamp)
{
	int ret = video_h264_get_data(data, max_size, is_iframe, timestamp);
	*timestamp += video_encode_start_time;
    return ret;
}

int app_hal_play_encoded_audio(void *data, uint32_t size, long long *timestamp)
{
    return app_audio_play(data, size, 8000);
}

int app_hal_start_video_encode(int start)
{
	int ret;
	if(start) {
		ret = h264_vpu_encode_start();
		if(ret < 0) {
			return -1;
		}
		video_encode_start_time = aos_now_ms();
	} else {
		h264_vpu_encode_stop();
	}
	return 0;
}

int app_hal_start_audio_encode(int start)
{
	if(start) {
		audio_encode_start_time = aos_now_ms();
		app_audio_record_start();
	} else {
		app_audio_record_stop();
	}
	return 0;
}

int app_hal_get_device_id(char * dev_id)
{
	extern uint8_t g_mac_addr[6];
	snprintf(dev_id, 13, "%02x%02x%02x%02x%02x%02x", g_mac_addr[0], g_mac_addr[1], g_mac_addr[2], \
														g_mac_addr[3], g_mac_addr[4], g_mac_addr[5]);
	return 0;
}

static cx_encvideo_format_t video_format;
static cx_encaudio_format_t audio_format;
int app_hal_get_video_attrs(cx_encvideo_format_t *fmt) {
	memcpy(fmt, &video_format, sizeof(cx_encvideo_format_t));
	return 0;
}

int app_hal_get_audio_attrs(cx_encaudio_format_t *fmt) {
	memcpy(fmt, &audio_format, sizeof(cx_encaudio_format_t));
	return 0;
}

int app_hal_set_playvideo_attrs(cx_encvideo_format_t *format) {
	memcpy(&video_format, format, sizeof(cx_encvideo_format_t));
	return 0;
}

int app_hal_set_playaudio_attrs(cx_encaudio_format_t *format) {
	memcpy(&audio_format, format, sizeof(cx_encaudio_format_t));
	return 0;
}
void cx_app_init(void)
{
	cx_hal_cbs_t cx_cbs;
	cx_cbs.get_raw_image = app_hal_get_raw_image;
	cx_cbs.start_video_encode = app_hal_start_video_encode;
	cx_cbs.start_audio_encode = app_hal_start_audio_encode;
	cx_cbs.get_encoded_audio = app_hal_get_encoded_audio;
	cx_cbs.get_encoded_video = app_hal_get_encoded_video;
    cx_cbs.video_seek_iframe = video_h264_seek_iframe;
    cx_cbs.play_encoded_audio  = app_hal_play_encoded_audio;
	cx_cbs.get_device_id = app_hal_get_device_id;
	cx_cbs.get_video_attrs = app_hal_get_video_attrs;
	cx_cbs.get_audio_attrs = app_hal_get_audio_attrs;
	cx_cbs.set_playvideo_attrs = app_hal_set_playvideo_attrs;
	cx_cbs.set_playaudio_attrs = app_hal_set_playaudio_attrs;
	cx_init(&cx_cbs);

	cx_encvideo_format_t video_format;
	video_format.fps = 25;
	video_format.encoding = CX_VIDEO_FORMAT_H264;
	cx_set_playvideo_attributes(&video_format);
	cx_encaudio_format_t audio_format;
	audio_format.freq = 8000;
	audio_format.sample_bwidth = 16;
	audio_format.channel = CX_AUDIO_CHANNEL_MONO;
	audio_format.encoding = CX_AUDIO_FORMAT_G711A;
	cx_set_playaudio_attributes(&audio_format);

	cx_record_param_t rec_param;
	rec_param.save_type = CX_RECORD_VIDEO_SAVE_BY_FRAME;
	rec_param.store_path = "/sdcard/record";
	cxrecord_hdl = cx_vr_init(&rec_param);

	aos_msleep(1000);
}